#ifndef VERTEX_H
#define VERTEX_H

#include "Vec.h"
#include "Mat.h"

/************************************************************
 * Class de sommet de base
 ************************************************************/
struct Vertex {
    Vec p, n;	//Position and normal of the vertex
	Vec u,v;	//Orthonormal coordinate system vectors in the tangent plane
	Mat weingarten;
	Mat derivative;
	double theta;
	
    inline Vertex () {}
    inline Vertex (const Vec & p) : p (p) {}
    inline Vertex (const Vec & p, const Vec & n) : p (p), n (n) {}
    inline Vertex (const Vertex & v) : p (v.p), n (v.n) {}
	
    inline virtual ~Vertex () {}
	
    inline Vertex & operator= (const Vertex & v)
	{
        p = v.p;
        n = v.n;
        return (*this);
    }
	
	inline double getCurvature(Vec vertexToCam)
	{
		theta = acos(vertexToCam * n);
		
		Vec vec = vertexToCam - (vertexToCam *n) * n;
		vec.normalize();
		
		Mat w(2,1);
		w(0,0) = vec * u;
		w(1,0) = vec * v;
		
		double norm = Vec(w(0,0), w(1,0),0).length();
		
		return( (w.transpose() * weingarten * w)(0,0)/norm );
	}

	inline double getTorsion(Vec vertexToCam)
	{
		theta = acos(vertexToCam * n);
		
		Vec vec = vertexToCam - (vertexToCam *n) * n;
		vec.normalize();
		
		Mat w(2,1);
		w(0,0) = vec * u;
		w(1,0) = vec * v;
		
		vec = n ^ vec;
		
		Mat w_prime(2,1);
		w_prime(0,0) = vec * u;
		w_prime(1,0) = vec * v;
		
		return( (w_prime.transpose() * weingarten * w)(0,0) );
	}

	inline double getCurvatureDerivative(Vec vertexToCam)
	{
		Vec vec = vertexToCam - (vertexToCam *n) * n;
		vec.normalize();
		
		Mat w(2,1);
		w(0,0) = vec * u;
		w(1,0) = vec * v;
		
		Mat temp = derivative * w;
		Mat temp2(2,2);
		
		temp2(0,0) = temp(0,0);
		temp2(0,1) = temp(1,0);
		temp2(1,0) = temp(2,0);
		temp2(1,1) = temp(3,0);
		
		return( ((temp2 * w).transpose() * w)(0,0) );
	}

};


#endif // VERTEX_H
